import { ref, computed, onMounted, h, watch } from "vue";
import { message } from "@/utils/message";
import { ElMessageBox } from "element-plus";
import {
  type RiskRuleSchema,
  type RiskTemplateMetadataSchema,
  getRiskRules,
  createOrUpdateRiskRule,
  deleteRiskRule,
  getRiskTemplates
} from "@/api/risk";
import { getAllTradeAppSettings } from "@/api/settings";
import { isTouchDevice, useBreakpointQuery } from "@/utils/device";
import type { PlusColumn, PlusDialogProps } from "plus-pro-components";
import { ElTag, ElTooltip } from "element-plus";
import Info from "~icons/ep/info-filled";
import { toRiskArgumentLines } from "@/utils/riskFormatting";

type DialogMode = "new" | "edit" | "copy";

export type RiskRuleClient = {
  name: string;
  trade_app_name: string;
  template: string;
  arguments: Record<string, any>;
  enabled: boolean;
  gateway_name?: string;
};

const emptyModel = (): RiskRuleClient => ({
  name: "",
  trade_app_name: "",
  template: "",
  arguments: {},
  enabled: true,
  gateway_name: ""
});

function toClient(payload: RiskRuleSchema): RiskRuleClient {
  return {
    name: payload.name,
    trade_app_name: payload.trade_app_name,
    template: payload.template,
    enabled: payload.enabled,
    gateway_name: payload.gateway_name || "",
    arguments: payload.arguments || {}
  };
}

function toServer(payload: RiskRuleClient): RiskRuleSchema {
  const args = Object.keys(payload.arguments || {}).reduce(
    (acc, key) => {
      const value = (payload.arguments || {})[key];
      if (value !== undefined && value !== null && value !== "") {
        acc[key] = value;
      }
      return acc;
    },
    {} as Record<string, any>
  );

  return {
    name: payload.name,
    trade_app_name: payload.trade_app_name,
    template: payload.template,
    enabled: payload.enabled,
    arguments: args
  };
}

function formatDocstring(doc: string): string {
  if (!doc) return "";
  const trimmed = doc.replace(/^\s+|\s+$/g, "");
  if (!trimmed) return "";
  const escapeHtml = (str: string) =>
    str
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;")
      .replace(/"/g, "&quot;")
      .replace(/'/g, "&#39;");
  const lines = trimmed.split("\n").map(line => {
    const match = line.match(/^(\s*)(.*)$/);
    if (!match) return escapeHtml(line);
    const spaces = match[1] || "";
    const content = match[2] || "";
    const nbsp = "&nbsp;".repeat(spaces.replace(/\t/g, "  ").length);
    return `${nbsp}${escapeHtml(content)}`;
  });
  return lines.join("<br />");
}

export function useRiskRulesPage() {
  const { isMdUp } = useBreakpointQuery();

  // data sources
  const riskTemplates = ref<RiskTemplateMetadataSchema[]>([]);
  const tradeAppNames = ref<string[]>([]);
  const templateDocMap = computed<Record<string, string>>(() => {
    const map: Record<string, string> = {};
    riskTemplates.value.forEach(tpl => {
      map[tpl.template] = formatDocstring(tpl.docstring);
    });
    return map;
  });

  // table state
  const tableData = ref<RiskRuleClient[]>([]);
  const searchQuery = ref("");
  const currentRow = ref<RiskRuleClient | null>(null);

  const tableSize = computed(() => (isMdUp() ? "default" : "small"));

  const tableColumns: TableColumnList = [
    {
      label: "规则名称",
      prop: "name",
      sortable: true,
      minWidth: 120,
      showOverflowTooltip: true
    },
    {
      label: "交易APP",
      prop: "trade_app_name",
      sortable: true,
      minWidth: 120,
      showOverflowTooltip: true
    },
    {
      label: "CTP配置",
      prop: "gateway_name",
      minWidth: 100,
      showOverflowTooltip: true
    },
    {
      label: "模板",
      prop: "template",
      sortable: true,
      minWidth: 150,
      cellRenderer: ({ row }) => {
        const doc = templateDocMap.value[row.template] || "";
        const tooltipContent = doc
          ? `<div class="font-mono whitespace-pre-wrap break-words text-xs leading-5">${doc}</div>`
          : "";
        return h("div", { class: "flex items-center gap-1" }, [
          h("span", row.template),
          doc &&
            h(
              ElTooltip,
              {
                content: tooltipContent,
                placement: "top",
                effect: "dark",
                rawContent: true,
                popperClass: "whitespace-pre-wrap max-w-md"
              },
              {
                default: () =>
                  h(Info, {
                    class: "cursor-help text-info hover:text-primary",
                    style: "font-size: 14px;"
                  })
              }
            )
        ]);
      }
    },
    {
      label: "参数",
      prop: "arguments",
      minWidth: 180,
      showOverflowTooltip: true,
      cellRenderer: ({ row }) => {
        const lines = toRiskArgumentLines(row.arguments);
        const text = lines.length ? lines.join("\n") : "—";
        return h(
          "pre",
          {
            class:
              "m-0 w-full whitespace-pre-wrap break-words font-mono text-xs leading-5 text-text_color_primary"
          },
          text
        );
      }
    },

    {
      label: "状态",
      prop: "enabled",
      width: 80,
      align: "center",
      filters: [
        { text: "启用", value: "启用" },
        { text: "禁用", value: "禁用" }
      ],
      filterMethod: (value: string, row: RiskRuleClient) => {
        return row.enabled === (value === "启用");
      },
      cellRenderer: ({ row }) =>
        h(
          ElTag,
          {
            type: row.enabled ? "success" : "info"
          },
          () => (row.enabled ? "启用" : "禁用")
        )
    }
  ];

  const filteredData = computed(() => {
    const q = (searchQuery.value || "").toLowerCase();
    if (!q) return tableData.value;
    return tableData.value.filter(row =>
      (row.name || "").toLowerCase().includes(q)
    );
  });

  const isRowSelected = computed(() => !!currentRow.value);

  const onCurrentChange = (row: RiskRuleClient | null) => {
    currentRow.value = row;
  };

  const onRowClick = (row: RiskRuleClient) => {
    if (!isTouchDevice()) return;
    onCurrentChange(row);
    openEdit();
  };

  // dialog state
  const dialogVisible = ref(false);
  const dialogMode = ref<DialogMode>("new");
  const dialogTitle = computed(() => {
    switch (dialogMode.value) {
      case "edit":
        return "编辑规则";
      case "copy":
        return "复制规则";
      default:
        return "新建规则";
    }
  });

  const dialogWidth = computed(() => (isMdUp() ? "720px" : "95vw"));

  const dialogProps = computed<PlusDialogProps>(() => ({
    title: dialogTitle.value,
    width: dialogWidth.value,
    closeOnClickModal: false,
    destroyOnClose: true
  }));

  const formRules = ref<Partial<Record<string, any[]>>>({
    name: [{ required: true, message: "请输入规则名称", trigger: "blur" }],
    trade_app_name: [
      { required: true, message: "请输入交易APP名称", trigger: "blur" }
    ],
    template: [{ required: true, message: "请输入模板", trigger: "blur" }]
  });

  const fetchTradeAppSuggestions = (
    queryString: string,
    cb: (list: any[]) => void
  ) => {
    const q = (queryString || "").toLowerCase();
    const list = tradeAppNames.value
      .filter(name => name.toLowerCase().includes(q))
      .map(name => ({ value: name }));
    cb(list);
  };

  const fetchTemplateSuggestions = (
    queryString: string,
    cb: (list: any[]) => void
  ) => {
    const q = (queryString || "").toLowerCase();
    const list = riskTemplates.value
      .filter(tpl => tpl.template.toLowerCase().includes(q))
      .map(tpl => ({ value: tpl.template }));
    cb(list);
  };

  const formColumns = ref<PlusColumn[]>([
    { label: "规则名称", prop: "name" },
    {
      label: "交易APP",
      prop: "trade_app_name",
      valueType: "autocomplete",
      fieldProps: {
        fetchSuggestions: fetchTradeAppSuggestions,
        placeholder: "请输入或选择交易APP",
        clearable: true
      }
    },
    {
      label: "模板",
      prop: "template",
      valueType: "autocomplete",
      fieldProps: {
        fetchSuggestions: fetchTemplateSuggestions,
        placeholder: "请输入或选择模板",
        clearable: true
      }
    },
    { label: "启用状态", prop: "enabled", valueType: "switch" },
    { label: "参数配置", prop: "arguments", colProps: { span: 24 } }
  ]);

  const dialogModel = ref<RiskRuleClient>(emptyModel());

  const selectedTemplate = computed(() =>
    riskTemplates.value.find(tpl => tpl.template === dialogModel.value.template)
  );

  const selectedTemplateDoc = computed(
    () => templateDocMap.value[dialogModel.value.template] || ""
  );

  const selectedTemplateSchema = computed(
    () => selectedTemplate.value?.argument_schema?.properties || {}
  );

  const selectedTemplateRequired = computed(
    () => selectedTemplate.value?.argument_schema?.required || []
  );

  watch(
    () => ({
      template: dialogModel.value.template,
      schema: selectedTemplateSchema.value
    }),
    ({ template, schema }) => {
      if (!template) {
        dialogModel.value.arguments = {};
        return;
      }
      const props = schema || {};
      const propKeys = Object.keys(props);
      if (!propKeys.length) return;
      const nextArgs: Record<string, any> = {};
      propKeys.forEach(key => {
        const schemaEntry = props[key] || {};
        const existing = dialogModel.value.arguments?.[key];
        if (existing !== undefined) {
          nextArgs[key] = existing;
        } else if (schemaEntry.default !== undefined) {
          nextArgs[key] = schemaEntry.default;
        } else if (schemaEntry.type === "boolean") {
          nextArgs[key] = false;
        } else if (
          schemaEntry.type === "number" ||
          schemaEntry.type === "integer"
        ) {
          nextArgs[key] = null;
        } else {
          nextArgs[key] = "";
        }
      });
      dialogModel.value.arguments = nextArgs;
    },
    { deep: false, immediate: true }
  );

  const dialogFormProps = computed(() => ({
    columns: formColumns.value,
    rules: formRules.value,
    labelWidth: "100px",
    clearable: true,
    colProps: { span: isMdUp() ? 12 : 24 },
    rowProps: { gutter: 20 }
  }));

  const openNew = () => {
    dialogMode.value = "new";
    dialogModel.value = emptyModel();
    dialogVisible.value = true;
  };

  const openEdit = () => {
    if (!currentRow.value) return;
    dialogMode.value = "edit";
    dialogModel.value = JSON.parse(JSON.stringify(currentRow.value));
    dialogVisible.value = true;
  };

  const openCopy = () => {
    if (!currentRow.value) return;
    dialogMode.value = "copy";
    const copy = JSON.parse(JSON.stringify(currentRow.value)) as RiskRuleClient;
    copy.name = "";
    dialogModel.value = copy;
    dialogVisible.value = true;
  };

  const handleDelete = () => {
    if (!currentRow.value) return;
    ElMessageBox.confirm(
      `确认删除规则 "${currentRow.value.name}" 吗?`,
      "提示",
      {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }
    )
      .then(async () => {
        try {
          if (currentRow.value?.name) {
            await deleteRiskRule(currentRow.value.name);
            message("规则删除成功", { type: "success" });
            await fetchAll();
            currentRow.value = null;
          }
        } catch (err) {
          message(`删除失败: ${err}`, { type: "error" });
        }
      })
      .catch(() => {
        // cancel
      });
  };

  const closeDialog = () => {
    dialogVisible.value = false;
  };

  const handleConfirm = async (values: any) => {
    try {
      const payload = values as RiskRuleClient;
      const serverPayload = toServer(payload);
      const res = await createOrUpdateRiskRule(serverPayload);
      if (!res?.success) {
        throw new Error(res?.message || "规则提交失败");
      }
      const action = dialogMode.value === "edit" ? "更新" : "创建";
      message(res?.message || `规则${action}成功`, { type: "success" });
      closeDialog();
      await fetchAll();
    } catch (err) {
      message(`提交规则失败: ${err}`, { type: "error" });
    }
  };

  const handleConfirmError = () => {
    message("请填写所有必填字段", { type: "warning" });
  };

  const fetchAll = async () => {
    try {
      const res = await getRiskRules();
      const list = ((res as any)?.data || []).map(toClient);
      tableData.value = list;
    } catch {
      message("获取风控规则失败", { type: "error" });
    }
  };

  const fetchMetadata = async () => {
    try {
      const [templatesRes, tradeAppsRes] = await Promise.all([
        getRiskTemplates(),
        getAllTradeAppSettings()
      ]);
      riskTemplates.value = (templatesRes as any)?.data || [];
      const tradeAppList = ((tradeAppsRes as any)?.data || []) as any[];
      tradeAppNames.value = Array.from(
        new Set(tradeAppList.map(app => app.name))
      );
    } catch (err) {
      console.error(err);
      message("获取模板或交易APP失败", { type: "error" });
    }
  };

  onMounted(() => {
    fetchAll();
    fetchMetadata();
  });

  return {
    // header
    searchQuery,
    openNew,
    openEdit,
    openCopy,
    handleDelete,
    isRowSelected,

    // table
    tableColumns,
    tableSize,
    filteredData,
    onCurrentChange,
    onRowClick,

    // dialog/form
    dialogVisible,
    dialogProps,
    dialogFormProps,
    dialogModel,
    handleConfirm,
    handleConfirmError,
    closeDialog,

    // template meta
    selectedTemplateDoc,
    selectedTemplateSchema,
    selectedTemplateRequired
  };
}
